package com.ftg.learn.chapter04.linetable;

import javax.swing.*;

/**
 * 链表
 *
 * @author 布衣
 */
public class LinkedListForMe<E>  implements MyList<E>{

//    线性存储结构 :
//        链式 ： 链表
//            单向链表
//            双向链表
//            循环链表
//        顺序 ： 数组

    //    先来实现单向链表
//    我们把链表当中每一个存储单元 ： 叫节点
//    每一个节点由两部分组成  [数据域]【指针域】     【指针域】[数据域]【指针域】
//    面向对象的思想 ：
    //链表 头节点
    private NodeForMe<E> head;

    //链表的 尾部
    private NodeForMe<E> tail;

    private int size;

    //头插法

    //尾插法
    public boolean insertTail(E val) {
        size++;
        if (head == null) {
            head = new NodeForMe<>(val);
            tail = head;
            return true;
        }

        tail.setNext(new NodeForMe<>(val));
        tail = tail.getNext();
        //找到最后一个节点
        //循环
//        NodeForMe temp = head;
//        while (temp.getNext() != null) {
//            temp = temp.getNext();
//        }
//        temp.setNext(new NodeForMe(val));
        //递归
//        NodeForMe temp = getTail(head);
//        temp.setNext(new NodeForMe(val));
        return true;
    }

    private NodeForMe<E> getTail(NodeForMe<E> current) {
        if (head == null) {
            return null;
        }

        if (current.getNext() == null) {
            return current;
        }
        return getTail(current.getNext());
    }

    /**
     * 获取链表的长度
     *
     * @return 长度
     */
    public int size() {
        return size;
    }

    public boolean insertHead(E val) {
        NodeForMe<E> node = new NodeForMe<>(val);
        size++;
        if (head == null) {
            head = node;
            tail = head;
            return true;
        }
        node.setNext(head);
        head = node;
        return true;
    }

    @Override
    public boolean add(E val) {
        return insertHead(val);
    }

    /**
     * 获取相应的链表下标对应的内容
     *
     * @param index 下标
     * @return E
     */
    public E get(int index) {
        return getNodeByIndex(index) == null ? null : getNodeByIndex(index).getData();
    }

    public NodeForMe<E> getNodeByIndex(int index) {
        if (index > size - 1) {
            return null;
        }
        if (head == null) {
            return null;
        }
        if (index < 0) {
            throw new RuntimeException("对不起，请输入正确的下标，不能小于0");
        }
        if (index == 0) {
            return head;
        }

        if (index == size - 1) {
            return tail;
        }

        int no = 0;
        NodeForMe<E> temp = head;
        while (temp != null) {
            if (no == index) {
                return temp;
            }
            temp = temp.getNext();
            no++;
        }
        return null;
    }

    public boolean deleteByIndex(int index) {
        if (index > size - 1) {
            throw new RuntimeException("下标超界");
        }
        if (head == null) {
            throw new RuntimeException("下标超界");
        }
        if (index < 0) {
            throw new RuntimeException("对不起，请输入正确的下标，不能小于0");
        }

        size--;

        if (index == 0) {
//            head = head.getNext();
            NodeForMe<E> temp = head;
            head = head.getNext();
            temp.setNext(null);
            return true;
        }

        if (index == size - 1) {
            NodeForMe<E> nodeByIndex = getNodeByIndex(index - 1);
            nodeByIndex.setNext(null);
            return true;
        }

        NodeForMe<E> nodeByIndex = getNodeByIndex(index - 1);
        NodeForMe<E> temp = nodeByIndex.getNext();
        nodeByIndex.setNext(temp.getNext());
        temp.setNext(null);
        return true;
    }

    public static void main(String[] args) {
        LinkedListForMe<Integer> l = new LinkedListForMe<>();
        l.insertTail(4);
        l.insertTail(5);
        l.insertTail(6);
        l.insertTail(7);

        l.deleteByIndex(2);

        System.out.println(l.get(0));
        System.out.println(l.get(1));
        System.out.println(l.get(2));
        System.out.println(l.get(3));
        // 1 链表要求自己会写

        // 2 160 234 141 206 前四个

        //0 反转链表 [再看]
        //1 把查找   删除方法看明白了
        //2 循环链表  当前的判断 想明白一下

        //3 问题  约瑟夫环  [链表]
        //4 160 234 141 206 前四个
    }

}
